/*
 * SIT_Label.c : static label text/image
 *
 * Written by T.Pierron, June 3, 2006.
 */

#include "SIT_P.h"
#include <stdio.h>
#include <ctype.h>

	TagList LabelClass[] = {
		{ SIT_SuperClass, NULL,         ___, SIT_INT,  (ULONG) WidgetClass },
		{ SIT_AlignHoriz, "alignHoriz", C__, SIT_INT,  OFFSET(SIT_Label, sl_Center) },
		{ SIT_Overflow,   "overflow",   _SG, SIT_INT,  OFFSET(SIT_Label, sl_Overflow) },
		{ SIT_FrameStyle, "frameStyle", C__, SIT_INT,  OFFSET(SIT_Label, sl_Frame) },
		{ SIT_HTMLLink,   "HTMLLink",   C__, SIT_BOOL, OFFSET(SIT_Label, sl_SysLink) },
		{ SIT_TagEnd }
	};

static void SIT_RemoveHTML(LPWSTR str)
{
	LPWSTR p, end;
	int ch;
	for (p = str; *p; )
	{
		switch (*p) {
		case '<':
			for (end = p + 1; *end && *end != '>'; end ++);
			if (*end) wcscpy(p, end + 1);
			break;
		case '&':
			if (wcscmpi(p + 1, L"lt;") == 0)  ch = '<', end = p + 4; else
			if (wcscmpi(p + 1, L"gt;") == 0)  ch = '>', end = p + 4; else
			if (wcscmpi(p + 1, L"amp;") == 0) ch = '&', end = p + 5; else { p ++; break; }
			*p ++ = ch; wcscpy(p, end);
			break;
		default: p ++;
		}
	}
}

/*
 * Considering the width of the label is fixed, compute how many lines is required to display the text.
 * This is used to constraint long labels.
 */
void SIT_LabelMinHeight(SIT_Widget lab, HDC hdc, LPWSTR str, int width)
{
	RECT r = {.right = width};

	lab->sw_OptimalBox.cx = width;
	lab->sw_OptimalBox.cy = DrawTextEx(hdc, str, -1, &r, DT_CALCRECT|DT_TABSTOP|DT_WORDBREAK, NULL);
}

static int SIT_MeasureLabel(SIT_Widget w, APTR cd, APTR ud)
{
	SIT_Label lab  = (SIT_Label) w;
	SIZE *    pref = cd;
	if (lab->sl_Frame == SITV_EtchedHoriz)
	{
		pref->cy = 2;
	}
	else if (lab->sl_Frame == SITV_EtchedVert)
	{
		pref->cx = 2;
	}
	else
	{
		LPWSTR  str, next, wstr;
		HDC     hdc = GetDC(w->sw_Handle);
		HGDIOBJ old = SelectObject(hdc, w->sw_Font);

		if (IsDef(w->sw_Title))
			UTF8ToUTF16(w->sw_Title, str)
		else
			str = w->sw_Name;

		if (lab->sl_SysLink) SIT_RemoveHTML(str);

		if (pref->cx > 0)
		{
			/* Constraint height according to desired width */
			RECT r = {.right = pref->cx};

			pref->cy = DrawTextEx(hdc, str, -1, &r, DT_CALCRECT|DT_TABSTOP|DT_WORDBREAK, NULL);
		}
		else
		{
			SIZE sz;
			/* Not sure if DrawTextEx can be usedin this case */
			for (wstr = str, pref->cy = 0; *str; str = next)
			{
				for (next = str; *next && *next != '\n'; next ++)
					if (*next == '&' && next[1]) wcscpy(next, next + 1);
				GetTextExtentPoint32(hdc, str, next - str, &sz);
				if (pref->cx < sz.cx) pref->cx = sz.cx;
				pref->cy += sz.cy;
				if (*next) next ++;
				if (*next == '\r') next ++;
			}
		}

		SelectObject(hdc, old);
		ReleaseDC(w->sw_Handle, hdc);

		/* Add NC area size */
		RECT nc, client;
		GetWindowRect(w->sw_Handle, &nc);
		GetClientRect(w->sw_Handle, &client);
		pref->cx += nc.right  - nc.left - client.right;
		pref->cy += nc.bottom - nc.top  - client.bottom;
	}
	return 0;
}

BOOL SIT_CreateLabel(SIT_Widget w, va_list args)
{
	HWND      hwnd;
	SIT_Label label = (SIT_Label) w;
	int       style = WS_CHILD | WS_GROUP;
	int       ext   = 0;

	w->sw_OptimalWidth = SIT_MeasureLabel;
	w->sw_Flags       |= SITF_AutoHeight;

	SIT_ParseTags(w, args, w->sw_Class = LabelClass);

	switch (label->sl_Center) {
	case SITV_AlignLeft:   style |= SS_LEFT; break;
	case SITV_AlignCenter: style |= SS_CENTER; break;
	case SITV_AlignRight:  style |= SS_RIGHT; break;
	}

	switch (label->sl_Overflow) {
	case SITV_Multiline:    break;
	case SITV_Hidden:       style |= SS_LEFTNOWORDWRAP; break;
	case SITV_ElipsisRight: style |= SS_ENDELLIPSIS; break;
	case SITV_ElipsisPath:  style |= SS_PATHELLIPSIS; break;
	}

	switch (label->sl_Frame) {
	case SITV_NoFrame:     break;
	case SITV_EtchedHoriz: style |= SS_ETCHEDHORZ; break;
	case SITV_EtchedVert:  style |= SS_ETCHEDVERT; break;
	case SITV_Etched:      style |= SS_ETCHEDFRAME; break;
	case SITV_Sunken:      style |= SS_BLACKFRAME; break;
	case SITV_Raised:      style |= SS_WHITEFRAME; break;
	case SITV_RaisedThick: style |= WS_THICKFRAME;
	case SITV_SunkenThick: ext = WS_EX_CLIENTEDGE; break;
	}

	if (IsVisible(w)) style |= WS_VISIBLE;

	/* Create Win32 control, pos and dim will be set later */
	hwnd = w->sw_Handle = CreateWindowEx(ext, label->sl_SysLink && has_syslink ? WC_LINK :
		WC_STATIC, w->sw_Name, style, 0, 0, 10, 10, SIT_GetContainer(w), (HMENU) MAKE_ID(w),
		instance, NULL);

	if (hwnd == NULL) return FALSE;
	SIT_SetDefaultFont(w);

	/* XXX might cause some side effects */
	SetClassLong(hwnd, GCL_STYLE, GetClassLong(hwnd, GCL_STYLE) | CS_HREDRAW);

	if (w->sw_Title)
		SIT_SetTitle(w);

	/* Keep track of class inside callback */
	SetProp(hwnd, sit_class, (HANDLE) w);

	return TRUE;
}

void SIT_CreateBuddyLabel(SIT_Widget buddy, STRPTR text, SIT_Widget * max)
{
	int    len  = WideCharToMultiByte(CP_UTF8, 0, buddy->sw_Name, -1, NULL, 0, NULL, NULL);
	STRPTR name = alloca(len+1);

	name[0] = 'b';
	WideCharToMultiByte(CP_UTF8, 0, buddy->sw_Name, -1, name + 1, len, NULL, NULL);
	SIT_Widget label = SIT_CreateWidget(name, SIT_LABEL, buddy->sw_Parent,
		SIT_AlignHoriz, SITV_AlignRight,
		SIT_Title,      text,
		SIT_Top,        SITV_AttachMiddle, buddy, 0,
		SIT_MaxWidth,   max ? *max : NULL,
		SIT_TabOrder,   buddy->sw_TabOrder - 1,
		NULL
	);
	LOGFONT font;
	GetObject(label->sw_Font, sizeof font, &font);
	len = ABS(font.lfHeight) / 2;
	SIT_SetValues(buddy, SIT_Left, SITV_AttachWidget, label, len, NULL);
	if (max) *max = label;
}
